# coding: utf-8

import copy
import types

class AttributeDict(dict):
    """
    This class defines the sqlmap object, inheriting from Python data
    type dictionary.
    >>> foo = AttributeDict()
    >>> foo.bar = 1
    >>> foo.bar
    1
    """
    def __init__(self, indict=None, attribute=None):
        if indict is None:
            indict = {}
        # Set any attributes here - before initialisation
        # these remain as normal attributes
        self.attribute = attribute
        dict.__init__(self, indict)
        self.__initialised = True
        # After initialisation, setting attributes
        # is the same as setting an item

    def __getattr__(self, item):
        """
        Maps values to attributes
        Only called if there *is NOT* an attribute with this name
        """
        try:
            return self.__getitem__(item)
        except KeyError:
            #raise AttributeError("unable to access item '%s'" % item)
            pass
        return None

    def __setattr__(self, item, value):
        """
        Maps attributes to values
        Only if we are initialised
        """
        # This test allows attributes to be set in the __init__ method
        if "_AttributeDict__initialised" not in self.__dict__:
            return dict.__setattr__(self, item, value)
        # Any normal attributes are handled normally
        elif item in self.__dict__:
            dict.__setattr__(self, item, value)
        else:
            self.__setitem__(item, value)

    def __getstate__(self):
        return self.__dict__

    def __setstate__(self, dict):
        self.__dict__ = dict

    def __deepcopy__(self, memo):
        retVal = self.__class__()
        memo[id(self)] = retVal
        for attr in dir(self):
            if not attr.startswith('_'):
                value = getattr(self, attr)
                if not isinstance(value, (types.BuiltinFunctionType, types.FunctionType, types.MethodType)):
                    setattr(retVal, attr, copy.deepcopy(value, memo))
        for key, value in self.items():
            retVal.__setitem__(key, copy.deepcopy(value, memo))
        return retVal


    def mapper(self, classes):
        instance = classes()
        items = self.items()
        attributes = dir(instance)
        for (key, value) in items:
            if attributes.count(key) == 0:
                continue
            instance._data[key] = value
        return instance